﻿using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using XYS.Core.Util;
using XYS.Core.Util.Helper;

namespace XYS.Core.Api.Filters
{    /// <summary>
     /// Add enum value descriptions to Swagger
     /// </summary>
    public class SwaggerEnumFilter : IDocumentFilter
    {
        readonly Dictionary<string, string> descriptionMaps = new();
        /// <summary>
        /// Apply
        /// </summary>
        /// <param name="swaggerDoc"></param>
        /// <param name="context"></param>
        public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context)
        {
            //获取所有枚举类型
            Dictionary<string, Type> dict = GetAllEnum();

            var schemas = swaggerDoc.Components.Schemas
                .Where(e => e.Value?.Enum != null
                && e.Value.Enum.Count > 0
                && dict.ContainsKey(e.Key));

            foreach (var item in schemas)
            {
                if (!descriptionMaps.TryGetValue(item.Key, out string description))
                {
                    var list = item.Value.Enum.Select(e => e as OpenApiInteger).ToList();
                    if (item.Key == "EnumStatusCode")
                        description = $"<br/>{Environment.NewLine}{string.Join("<br/>" + Environment.NewLine, GetEnumDescribes(dict[item.Key], list.Where(e => e.Value >= 600).ToList()))}";
                    else
                        description = $"<br/>{Environment.NewLine}{string.Join("<br/>" + Environment.NewLine, GetEnumDescribes(dict[item.Key], list))}";
                    //缓存
                    descriptionMaps[item.Key] = description;
                }

                item.Value.Description += description;
            }
        }

        /// <summary>
        /// 获取所有枚举
        /// </summary>
        /// <returns></returns>
        private static Dictionary<string, Type> GetAllEnum()
        {
            return AssemblyHelper.GetAssemblyTypes().Where(e => e.IsEnum == true && e.Namespace != "GrpcService").Distinct(e => e.Name).ToDictionary(t => t.Name, t => t);
        }

        /// <summary>
        /// 获取枚举的描述特性
        /// </summary>
        /// <param name="type">枚举类型</param>
        /// <param name="enums">枚举的值 列表</param>
        /// <returns></returns>
        private static List<string> GetEnumDescribes(Type type, List<OpenApiInteger> enums)
        {
            var enumDescriptions = new List<string>();
            if (type != null)
            {
                foreach (var item in enums)
                {
                    if (item != null)
                    {
                        object value = Enum.Parse(type, item.Value.ToString(), true);
                        var desc = EnumHelper.GetDescription(value);

                        enumDescriptions.Add($"{item.Value}:{value},{desc}");
                    }
                }
            }
            return enumDescriptions;
        }
    }

    /// <summary>
    /// Swagger文档枚举字段显示枚举属性和枚举值,以及枚举描述
    /// </summary>
    public class EnumSchemaFilter : ISchemaFilter
    {
        /// <summary>
        /// 实现接口
        /// </summary>
        /// <param name="model"></param>
        /// <param name="context"></param>

        public void Apply(OpenApiSchema model, SchemaFilterContext context)
        {
            if (context.Type.IsEnum)
            {
                var enumNames = Enum.GetNames(context.Type);

                foreach (var name in enumNames)
                {
                    string enumDesc = ((Enum)Enum.Parse(context.Type, name)).GetDescription();
                    string desc = $"{Convert.ToInt64(Enum.Parse(context.Type, name))}：{enumDesc}，{name}</br>";
                    model.Description += desc;
                }
            }
        }
    }
}
